package com.mini.mybatis.executor.resultset;

import com.mini.mybatis.mapping.MappedStatement;
import com.mini.mybatis.reflection.MetaObject;
import com.mini.mybatis.session.Configuration;
import com.mini.mybatis.type.TypeHandler;
import com.mini.mybatis.type.TypeHandlerRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 默认结果集处理器实现
 * 负责将ResultSet转换为Java对象
 */
public class DefaultResultSetHandler implements ResultSetHandler {
    
    private static final Logger logger = LoggerFactory.getLogger(DefaultResultSetHandler.class);
    
    private final Configuration configuration;
    private final MappedStatement mappedStatement;
    private final TypeHandlerRegistry typeHandlerRegistry;
    
    public DefaultResultSetHandler(Configuration configuration, MappedStatement mappedStatement) {
        this.configuration = configuration;
        this.mappedStatement = mappedStatement;
        this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
    }
    
    @Override
    @SuppressWarnings("unchecked")
    public <E> List<E> handleResultSets(Statement stmt) throws SQLException {
        final List<E> multipleResults = new ArrayList<>();
        
        int resultSetCount = 0;
        ResultSetWrapper rsw = getFirstResultSet(stmt);
        
        while (rsw != null && resultSetCount < 1) {
            List<E> resultSet = handleResultSet(rsw);
            if (resultSet != null) {
                multipleResults.addAll(resultSet);
            }
            rsw = getNextResultSet(stmt);
            resultSetCount++;
        }
        
        return multipleResults;
    }
    
    @Override
    public void handleOutputParameters(CallableStatement cs) throws SQLException {
        // 简化实现：暂不支持输出参数
        logger.debug("输出参数处理暂未实现");
    }
    
    /**
     * 处理单个结果集
     */
    @SuppressWarnings("unchecked")
    private <E> List<E> handleResultSet(ResultSetWrapper rsw) throws SQLException {
        final List<E> resultList = new ArrayList<>();
        
        Class<?> resultType = mappedStatement.getResultType();
        if (resultType == null) {
            logger.warn("结果类型未指定，使用Object类型");
            resultType = Object.class;
        }
        
        ResultSet resultSet = rsw.getResultSet();
        while (resultSet.next()) {
            E rowValue = (E) createResultObject(resultSet, resultType);
            resultList.add(rowValue);
        }
        
        return resultList;
    }
    
    /**
     * 创建结果对象
     */
    private Object createResultObject(ResultSet rs, Class<?> resultType) throws SQLException {
        if (resultType == null) {
            return null;
        }
        
        // 如果是基本类型，直接从第一列获取值
        if (typeHandlerRegistry.hasTypeHandler(resultType)) {
            return getValueFromFirstColumn(rs, resultType);
        }
        
        // 创建复杂对象并填充属性
        Object resultObject = instantiateClass(resultType);
        MetaObject metaObject = configuration.newMetaObject(resultObject);
        
        // 获取结果集元数据
        ResultSetMetaData rsmd = rs.getMetaData();
        int columnCount = rsmd.getColumnCount();
        
        // 遍历所有列，设置对象属性
        for (int i = 1; i <= columnCount; i++) {
            String columnName = rsmd.getColumnLabel(i);
            if (columnName == null) {
                columnName = rsmd.getColumnName(i);
            }
            
            // 将列名转换为属性名（简化处理：直接使用列名）
            String propertyName = columnName;
            
            if (metaObject.hasProperty(propertyName)) {
                Object value = getValueFromColumn(rs, i, rsmd.getColumnType(i));
                metaObject.setValue(propertyName, value);
            }
        }
        
        return resultObject;
    }
    
    /**
     * 从第一列获取值（用于基本类型）
     */
    private Object getValueFromFirstColumn(ResultSet rs, Class<?> targetType) throws SQLException {
        TypeHandler<?> typeHandler = typeHandlerRegistry.getTypeHandler(targetType);
        return typeHandler.getResult(rs, 1);
    }
    
    /**
     * 从指定列获取值
     */
    private Object getValueFromColumn(ResultSet rs, int columnIndex, int sqlType) throws SQLException {
        // 根据SQL类型选择合适的获取方法
        switch (sqlType) {
            case Types.VARCHAR:
            case Types.CHAR:
            case Types.LONGVARCHAR:
                return rs.getString(columnIndex);
            case Types.BIGINT:
                long longValue = rs.getLong(columnIndex);
                return rs.wasNull() ? null : longValue;
            case Types.INTEGER:
                int intValue = rs.getInt(columnIndex);
                return rs.wasNull() ? null : intValue;
            case Types.SMALLINT:
            case Types.TINYINT:
                short shortValue = rs.getShort(columnIndex);
                return rs.wasNull() ? null : shortValue;
            case Types.DECIMAL:
            case Types.NUMERIC:
                return rs.getBigDecimal(columnIndex);
            case Types.REAL:
            case Types.FLOAT:
                float floatValue = rs.getFloat(columnIndex);
                return rs.wasNull() ? null : floatValue;
            case Types.DOUBLE:
                double doubleValue = rs.getDouble(columnIndex);
                return rs.wasNull() ? null : doubleValue;
            case Types.BIT:
            case Types.BOOLEAN:
                boolean boolValue = rs.getBoolean(columnIndex);
                return rs.wasNull() ? null : boolValue;
            case Types.DATE:
                return rs.getDate(columnIndex);
            case Types.TIME:
                return rs.getTime(columnIndex);
            case Types.TIMESTAMP:
                return rs.getTimestamp(columnIndex);
            default:
                return rs.getObject(columnIndex);
        }
    }
    
    /**
     * 实例化类
     */
    private Object instantiateClass(Class<?> type) {
        try {
            return configuration.getObjectFactory().create(type);
        } catch (Exception e) {
            throw new RuntimeException("无法实例化结果类型: " + type.getName(), e);
        }
    }
    
    /**
     * 获取第一个结果集
     */
    private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {
        ResultSet rs = stmt.getResultSet();
        while (rs == null) {
            // 移动到下一个结果集
            if (stmt.getMoreResults()) {
                rs = stmt.getResultSet();
            } else {
                if (stmt.getUpdateCount() == -1) {
                    // 没有更多结果集
                    break;
                }
            }
        }
        return rs != null ? new ResultSetWrapper(rs, configuration) : null;
    }
    
    /**
     * 获取下一个结果集
     */
    private ResultSetWrapper getNextResultSet(Statement stmt) throws SQLException {
        // 简化实现：只处理第一个结果集
        return null;
    }
    
    /**
     * 结果集包装器
     */
    private static class ResultSetWrapper {
        private final ResultSet resultSet;
        private final Configuration configuration;
        
        public ResultSetWrapper(ResultSet rs, Configuration configuration) {
            this.resultSet = rs;
            this.configuration = configuration;
        }
        
        public ResultSet getResultSet() {
            return resultSet;
        }
    }
}